#include "qnetworkhttpserver.h"
#include <QThread>
#include <QNetworkRequest>
#include <QFile>
#include <QHttpMultiPart>
#include <QNetworkReply>
#include <QUrlQuery>
#include <QJsonValue>
#include <QJsonObject>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <QCoreApplication>

#include "httplib.h"
#include <Windows.h>
#include <iostream>
#include <chrono>
#include <memory>

//#include "scope_exit.h"

class QNetworkHttpServerPrivate {

	QNetworkHttpServerPrivate();
	friend class QNetworkHttpServer;
	std::shared_ptr<httplib::Server> m_HttpServer;

	std::thread m_thread;

	QMutex   m_dataMutex; //

	bool m_started = false;
};

QNetworkHttpServerPrivate::QNetworkHttpServerPrivate()
{
	m_HttpServer = std::make_shared<httplib::Server>();
}

QNetworkHttpServer::QNetworkHttpServer(QObject* parent)
	: QObject(parent), d(new QNetworkHttpServerPrivate())
{
    //
}

QNetworkHttpServer::~QNetworkHttpServer()
{
	d->m_HttpServer->stop();
	if (d->m_thread.joinable())
		d->m_thread.join();

	delete d;
}

void QNetworkHttpServer::init()
{
	//
}

void QNetworkHttpServer::shutdown()
{
	QMutexLocker locker(&d->m_dataMutex);
	d->m_HttpServer->stop();
	if (d->m_thread.joinable())
		d->m_thread.join();
}

bool QNetworkHttpServer::listen(int port)
{
	QMutexLocker locker(&d->m_dataMutex);

	if (d->m_started) return true;

	d->m_thread = std::thread([this, port]() {
		d->m_HttpServer->listen("0.0.0.0", port);
		d->m_started = true;
	});

	d->m_HttpServer->wait_until_ready();

	return true;
}

void QNetworkHttpServer::getJsonApi(const QString& path, SimpleJsonHandler handler)
{
	d->m_HttpServer->Get(path.toUtf8().toStdString(), [handler](const httplib::Request& req, httplib::Response& res) {
		SimpleRequest simpleRequest;
		simpleRequest.method = req.method;
		simpleRequest.path = req.path;
		simpleRequest.body = req.body;

		simpleRequest.remote_addr = req.remote_addr;
		simpleRequest.remote_port = req.remote_port;
		simpleRequest.local_addr = req.local_addr;
		simpleRequest.local_port = req.local_port;

		simpleRequest.params = req.params;
		simpleRequest.path_params = req.path_params;

		SimpleResponse simpleResponse;
		handler(simpleRequest, simpleResponse);

		res.status = simpleResponse.status;
		res.set_content(simpleResponse.body, "application/json");
	});
}

void QNetworkHttpServer::postJsonApi(const QString& path, SimpleJsonHandler handler)
{
	d->m_HttpServer->Post(path.toUtf8().toStdString(), [handler](const httplib::Request& req, httplib::Response& res) {
		SimpleRequest simpleRequest;
		simpleRequest.method = req.method;
		simpleRequest.path = req.path;
		simpleRequest.body = req.body;

		simpleRequest.remote_addr = req.remote_addr;
		simpleRequest.remote_port = req.remote_port;
		simpleRequest.local_addr = req.local_addr;
		simpleRequest.local_port = req.local_port;

		simpleRequest.params = req.params;
		simpleRequest.path_params = req.path_params;

		SimpleResponse simpleResponse;
		handler(simpleRequest, simpleResponse);

		res.status = simpleResponse.status;
		res.set_content(simpleResponse.body, "application/json");
	});
}